package com.treasure.service.rabbit.service;

import com.alibaba.fastjson.JSONObject;
import com.treasure.service.constant.mq.GlobalConstant;
import com.treasure.service.util.JAXBUtil;
import com.treasure.service.util.ObjectUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.amqp.core.Message;
import org.springframework.amqp.rabbit.core.RabbitTemplate;
import org.springframework.amqp.rabbit.support.CorrelationData;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

/**
 * @Description: 
 * @version 1.0 
 * @author panxinwen 2018/11/2 13:49
 * @Copyright © 2015 | 武汉京航科技有限公司 Email:19919866605@163.com
 * */

@Component
public class SendMQ implements RabbitTemplate.ConfirmCallback, RabbitTemplate.ReturnCallback {
    Logger logger = LoggerFactory.getLogger(SendMQ.class);
    private RabbitTemplate rabbitTemplate;

    /**
     * 构造方法注入
     */
    @Autowired
    public SendMQ(RabbitTemplate rabbitTemplate) {
        this.rabbitTemplate = rabbitTemplate;
        rabbitTemplate.setReturnCallback(this);
        rabbitTemplate.setConfirmCallback(this);//rabbitTemplate如果为单例的话，那回调就是最后设置的内容

    }


    /**
     * request/response模式
     *
     * @param key
     * @param content
     * @param id
     * @param type
     * @param c
     * @param <T>
     * @return
     */
    public <T> T sendMsgAndReceive(String key, Object content, String id, String type, Class<T> c) {
        String sendContent = "";
        switch (type) {
            case GlobalConstant.JSON:
                sendContent = JSONObject.toJSONString(content);
                break;
            case GlobalConstant.XML:
                sendContent = JAXBUtil.convertToXml(content);
                break;
            default:
                sendContent = JSONObject.toJSONString(content);
        }
        T receiveMsg = null;
        CorrelationData correlationId = new CorrelationData(id);

        logger.info("[synchronization]sendMsgAndReceive:id[{}],exchange[{}],routingKey[{}],message[{}]", correlationId.getId(), rabbitTemplate.getExchange(), key, content);
        Object obj = rabbitTemplate.convertSendAndReceive(rabbitTemplate.getExchange(), key, content, correlationId);
        receiveMsg = ObjectUtil.converyToBean(obj, c);

        logger.info("[synchronization]sendMsgAndReceive:id[{}],exchange[{}],routingKey[{}],message[{}],result[{}]", correlationId.getId(), rabbitTemplate.getExchange(), key, content, obj);
        return receiveMsg;
    }

    public void sendMsg(String key, Object content, String id, String type) {
        String sendContent = convertContent( content, type);
        sendMsg(key, sendContent, id);
    }

    public void sendMsg(String key, String content, String id) {
        CorrelationData correlationId = new CorrelationData(id);
        logger.info("[asynchronous]sendMsg:id[{}],exchange[{}],routingKey[{}],message[{}]", correlationId.getId(), rabbitTemplate.getExchange(), key, content);
        try {
            rabbitTemplate.convertAndSend(rabbitTemplate.getExchange(), key, content, correlationId);
        } catch (Exception e) {
        	logger.info("sendMsg error:{}",e);
            e.printStackTrace();
        }
    }
    protected String convertContent(Object content,String type){
        String sendContent = "";
        switch (type) {
            case GlobalConstant.JSON:
                sendContent = JSONObject.toJSONString(content);
                break;
            case GlobalConstant.XML:
                sendContent = JAXBUtil.convertToXml(content);
                break;
            default:
                sendContent = JSONObject.toJSONString(content);
        }
        return sendContent;
    }


    /**
     * 回调
     */
    @Override
    public void confirm(CorrelationData correlationData, boolean ack, String cause) {

    }

    @Override
    public void returnedMessage(Message message, int replyCode, String replyText, String exchange, String routingKey) {
        logger.info("returnback:{}", replyCode);
        try {
            Thread.sleep(GlobalConstant.ONE_SECOND);
        } catch (InterruptedException e) {
            e.printStackTrace();
            logger.info("returnedMessage error:{}",e);
        }
    }
}
